package cn.com.cym.gamezao.util;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

/**
 * 代码初始化生成
 */
public class CodeInitUtils {

    /**
     *
     * @param path 实体下面代码路径
     * @param className 类名
     */
    private static void generateCode(String path,String className){
        // 判断类是否存在 存在直接返回
        final String property = System.getProperty("user.dir")+"\\src\\main\\java\\cn\\com\\cym\\gamezao";
        File file = new File(property+"\\entity\\"+path+"\\"+className+".java");

        if(!file.exists()){
            System.out.println("------实体不存在，无法自动生成------");
            return;
        }

        generateRepositoryCode(path,className);
        generateServiceCode(path,className);
        generateImplCode(path,className);
        generateControllerCode(path,className);
    }

    private static void generateRepositoryCode(String path,String className){
        // 判断类是否存在 存在直接返回
        final String property = System.getProperty("user.dir")+"\\src\\main\\java\\cn\\com\\cym\\gamezao";
        System.out.println(property);
        File fileDir = new  File(property+"\\repository\\"+path);
        if(!(fileDir.exists() && fileDir.isDirectory())){
            fileDir.mkdir();
        }
        File file = new File(property+"\\repository\\"+path+"\\"+className+"Repository.java");

        if(file.exists()){
            System.out.println("------已经存在 Repository------");
            return;
        }else {
            try{
                file.createNewFile();
            }catch (IOException e){
                System.out.println(e.getMessage());
            }
        }

        System.out.println("------开始生成Repository------");
        StringBuffer sb = new StringBuffer("package cn.com.cym.gamezao.repository.").append(path).append(";\n");
        sb.append("import cn.com.cym.gamezao.base.BaseRepository;\n");
        sb.append("import org.springframework.data.redis.core.RedisHash;\n");
        sb.append("import org.springframework.stereotype.Repository;\n");
        sb.append("import cn.com.cym.gamezao.entity.").append(path).append(".").append(className).append(";\n");
        sb.append("\n");
        sb.append("@RedisHash\n@Repository\npublic interface ").append(className).append("Repository extends BaseRepository<").append(className).append(",Long> {");
        sb.append("\n}");
        System.out.println(sb.toString());
        FileWriter fileWriter = null;
        try{
            fileWriter = new FileWriter(property+"\\repository\\"+path+"\\"+className+"Repository.java",true);
            fileWriter.append(sb.toString());
        }catch (IOException e){
            System.out.println(e.getMessage());
        }finally {
            if(null != fileWriter ){
                try{
                    fileWriter.close();
                }catch (IOException e1){
                    System.out.println(e1.getMessage());
                }

            }
        }
        System.out.println("-----结束生成Repository------");
    }

    private static void generateServiceCode(String path,String className){
        // 判断类是否存在 存在直接返回
        final String property = System.getProperty("user.dir")+"\\src\\main\\java\\cn\\com\\cym\\gamezao";
        System.out.println(property);
        File fileDir = new  File(property+"\\service\\"+path);
        if(!(fileDir.exists() && fileDir.isDirectory())){
            fileDir.mkdir();
        }
        File file = new File(property+"\\service\\"+path+"\\"+className+"Service.java");

        if(file.exists()){
            System.out.println("------已经存在 Service------");
            return;
        }else {
            try{
                file.createNewFile();
            }catch (IOException e){
                System.out.println(e.getMessage());
            }
        }
        System.out.println("------开始生成Service------");
        StringBuffer sb = new StringBuffer("package cn.com.cym.gamezao.service.").append(path).append(";\n\n");
        sb.append("import cn.com.cym.gamezao.base.BaseService;\n");
        sb.append("import cn.com.cym.gamezao.entity.").append(path).append(".").append(className).append(";\n\n");
        sb.append("public interface ").append(className).append("Service extends BaseService<").append(className).append("> {\n}");
        System.out.println(sb.toString());
        FileWriter fileWriter = null;
        try{
            fileWriter = new FileWriter(property+"\\service\\"+path+"\\"+className+"Service.java",true);
            fileWriter.append(sb.toString());
        }catch (IOException e){
            System.out.println(e.getMessage());
        }finally {
            if(null != fileWriter ){
                try{
                    fileWriter.close();
                }catch (IOException e1){
                    System.out.println(e1.getMessage());
                }

            }
        }
        System.out.println("------结束生成Service------");
    }

    private static void generateImplCode(String path,String className){
        final String property = System.getProperty("user.dir")+"\\src\\main\\java\\cn\\com\\cym\\gamezao";
        System.out.println(property);
        File fileDir = new  File(property+"\\service\\"+path+"\\impl");
        if(!(fileDir.exists() && fileDir.isDirectory())){
            fileDir.mkdir();
        }
        File file = new File(property+"\\service\\"+path+"\\impl\\"+className+"Impl.java");

        if(file.exists()){
            System.out.println("------已经存在 Impl------");
            return;
        }else {
            try{
                file.createNewFile();
            }catch (IOException e){
                System.out.println(e.getMessage());
            }
        }
        System.out.println("------开始生成Impl------");
        StringBuffer sb = new StringBuffer("package cn.com.cym.gamezao.service.").append(path).append(".").append("impl").append(";\n\n");
        sb.append("import cn.com.cym.gamezao.base.BaseImpl;\n");
        sb.append("import cn.com.cym.gamezao.base.BaseRepository;\n");
        sb.append("import cn.com.cym.gamezao.base.SearchPage;\n");
        sb.append("import cn.com.cym.gamezao.entity.").append(path).append(".").append(className).append(";\n");
        sb.append("import cn.com.cym.gamezao.repository.").append(path).append(".").append(className).append("Repository;\n");
        sb.append("import cn.com.cym.gamezao.service.").append(path).append(".").append(className).append("Service;\n");
        sb.append("import cn.com.cym.gamezao.util.CommonUtils;\nimport cn.hutool.core.util.ReflectUtil;\nimport lombok.SneakyThrows;\n");
        sb.append("import org.springframework.data.domain.Page;\n").append("import org.springframework.data.domain.PageRequest;\n");
        sb.append("import org.springframework.data.domain.Pageable;\nimport org.springframework.data.jpa.domain.Specification;\nimport org.springframework.stereotype.Service;\n");
        sb.append("import org.springframework.transaction.annotation.Transactional;\n\nimport javax.persistence.criteria.CriteriaBuilder;\n");
        sb.append("import javax.persistence.criteria.CriteriaQuery;\nimport javax.persistence.criteria.Predicate;\nimport javax.persistence.criteria.Root;\n");
        sb.append("import java.lang.reflect.Field;\nimport java.util.Map;\n\n");
        sb.append("@Service\n@Transactional(rollbackFor = Exception.class)\n");
        sb.append("public class ").append(className).append("Impl extends BaseImpl<").append(className).append("> implements ").append(className).append("Service {\n\n");
        sb.append("    final ").append(className).append("Repository thisRepository;\n\n");
        sb.append("    public ").append(className).append("Impl(").append(className).append("Repository ").append(firstLower(className)).append("Repository){\n");
        sb.append("        this.thisRepository = ").append(firstLower(className)).append("Repository;\n");
        sb.append("    }\n\n");
        sb.append("    @Override\n").append("    public BaseRepository<").append(className).append(", Long> getJpaRepository() {\n");
        sb.append("        return thisRepository;\n").append("    }\n\n");
        sb.append("    @Override\n").append("    public Page<").append(className).append("> findByPageable(SearchPage searchPage) {\n");
        sb.append("        String[] sortBy = searchPage.getSortBy().toArray(new String[searchPage.getSortBy().size()]);\n");
        sb.append("        Pageable pageable = PageRequest.of(searchPage.getCurrent()-1, searchPage.getPageSize(), searchPage.getSort(), sortBy);\n");
        sb.append("        Specification<").append(className).append("> specification = new Specification<>() {\n");
        sb.append("            private static final long serialVersionUID = -2661077778894635593L;\n");
        sb.append("            @SneakyThrows\n            @Override\n");
        sb.append("            public Predicate toPredicate(Root<").append(className).append("> root,CriteriaQuery<?> query, CriteriaBuilder cb) {\n");
        sb.append("                final Map<String, Field> fieldMap = ReflectUtil.getFieldMap(").append(className).append(".class);\n");
        sb.append("                return cb.and(CommonUtils.pageSet(fieldMap,searchPage,cb,root));\n");
        sb.append("            }\n        };\n        return this.thisRepository.findAll(specification, pageable);\n    }\n}");
        // 判断类是否存在 存在直接返回
        System.out.println(sb);
        FileWriter fileWriter = null;
        try{
            fileWriter = new FileWriter(property+"\\service\\"+path+"\\impl\\"+className+"Impl.java",true);
            fileWriter.append(sb.toString());
        }catch (IOException e){
            System.out.println(e.getMessage());
        }finally {
            if(null != fileWriter ){
                try{
                    fileWriter.close();
                }catch (IOException e1){
                    System.out.println(e1.getMessage());
                }

            }
        }
        System.out.println("------结束生成Impl------");
    }

    private static void generateControllerCode(String path,String className){
        // 判断类是否存在 存在直接返回
        final String property = System.getProperty("user.dir")+"\\src\\main\\java\\cn\\com\\cym\\gamezao";
        System.out.println(property);
        File fileDir = new  File(property+"\\web\\"+path);
        if(!(fileDir.exists() && fileDir.isDirectory())){
            fileDir.mkdir();
        }
        File file = new File(property+"\\web\\"+path+"\\"+className+"Controller.java");

        if(file.exists()){
            System.out.println("------已经存在 Controller------");
            return;
        }else {
            try{
                file.createNewFile();
            }catch (IOException e){
                System.out.println(e.getMessage());
            }
        }

        System.out.println("------开始生成Controller------");
        StringBuffer sb = new StringBuffer("package cn.com.cym.gamezao.web.").append(path).append(";\n\n");
        sb.append("import cn.com.cym.gamezao.annotation.AuthToken;\n");
        sb.append("import cn.com.cym.gamezao.base.BaseController;\n");
        sb.append("import cn.com.cym.gamezao.base.BaseService;\n");
        sb.append("import cn.com.cym.gamezao.entity.").append(path).append(".").append(className).append(";\n");
        sb.append("import cn.com.cym.gamezao.service.").append(path).append(".").append(className).append("Service;\n");
        sb.append("import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;\nimport io.swagger.annotations.Api;\n");
        sb.append("import io.swagger.annotations.ApiImplicitParam;\nimport io.swagger.annotations.ApiImplicitParams;\nimport io.swagger.annotations.ApiOperation;\n");
        sb.append("import org.springframework.http.ResponseEntity;").append("\nimport org.springframework.web.bind.annotation.*;\n\n");

        sb.append("@Api(tags = \"").append(className).append("\")").append("\n@RestController\n").append("@RequestMapping(value = \"").append(firstLower(className)).append("\")\n");
        sb.append("@AuthToken(rule = \"").append(path).append(".").append(firstLower(className)).append("\")\n");
        sb.append("public class ").append(className).append("Controller extends BaseController<").append(className).append("> {\n");
        sb.append("    final ").append(className).append("Service thisService;\n\n");
        sb.append("    public ").append(className).append("Controller(").append(className).append("Service ").append(firstLower(className)).append("Service){\n");
        sb.append("        this.thisService=").append(firstLower(className)).append("Service;\n");
        sb.append("    }\n\n");
        sb.append("    @Override\n    public BaseService<").append(className).append("> getService() {\n");
        sb.append("        return this.thisService;\n    }\n\n");
        sb.append("    @ApiImplicitParam(name = \"").append(firstLower(className)).append("\", value = \"").append(firstLower(className)).append("\", required = true,dataType = \"").append(className).append("\")\n");
        sb.append("    @ApiOperation(value = \"新建\")\n");
        sb.append("    @ApiOperationSupport(order = 1, author = \"mr.chen\")\n");
        sb.append("    @PostMapping()\n");
        sb.append("    @AuthToken(rule = \"add\")\n");
        sb.append("    public ResponseEntity<?> add(@RequestBody ").append(className).append(" ").append(firstLower(className)).append("){\n");
        sb.append("        final ").append(className).append(" ").append(firstLower(className)).append("Store = this.thisService.save(").append(firstLower(className)).append(");\n");
        sb.append("        return ResponseEntity.ok(").append(firstLower(className)).append("Store);\n");
        sb.append("    }\n\n");
        sb.append("    @ApiImplicitParams({@ApiImplicitParam(name = \"id\", value = \"id\",paramType = \"path\", required = true,dataType = \"Long\"),\n");
        sb.append("            @ApiImplicitParam(name = \"").append(firstLower(className)).append("\", value = \"").append(firstLower(className)).append("\", required = true,dataType = \"").append(className).append("\")})\n");
        sb.append("    @ApiOperation(value = \"更新\")\n");
        sb.append("    @ApiOperationSupport(order = 3, author = \"mr.chen\")\n");
        sb.append("    @PutMapping(\"/{id}\")\n");
        sb.append("    @AuthToken(rule = \"update\")\n");
        sb.append("    public ResponseEntity<?> update(@RequestBody ").append(className).append(" ").append(firstLower(className)).append(",@PathVariable Long id){\n");
        sb.append("        final ").append(className).append(" ").append(firstLower(className)).append("Store = this.thisService.update(").append(firstLower(className)).append(",id);\n");
        sb.append("        return ResponseEntity.ok(").append(firstLower(className)).append("Store);\n");
        sb.append("    }\n\n");
        sb.append("}");

        System.out.println(sb);
        FileWriter fileWriter = null;
        try{
            fileWriter = new FileWriter(property+"\\web\\"+path+"\\"+className+"Controller.java",true);
            fileWriter.append(sb.toString());
        }catch (IOException e){
            System.out.println(e.getMessage());
        }finally {
            if(null != fileWriter ){
                try{
                    fileWriter.close();
                }catch (IOException e1){
                    System.out.println(e1.getMessage());
                }

            }
        }
        System.out.println("------结束生成Controller------");
    }

    /**
     * 第一个字符小写
     * @param className
     * @return
     */
    private static  String firstLower(String className){
        char[] cs=className.toCharArray();
        cs[0]+=32;
        return String.valueOf(cs);
    }

    private static  String firstUpper(String className){
        char[] cs=className.toCharArray();
        cs[0]-=32;
        return String.valueOf(cs);
    }

    public static void main(String[] args) {
        System.out.println("-----------------------------------------------代码开始生成--------------------------------------------------------");
        generateCode("single","VaccineReg");
        System.out.println("-----------------------------------------------代码开始结束--------------------------------------------------------");
    }
}
